package cn.handong.tool.沪房;

import org.junit.Test;

import javax.persistence.criteria.CriteriaBuilder;
import java.text.DecimalFormat;

/**
 * 等额本金提前还款计算方法：
 * 1、提前还后的本金是 剩余本金 / 剩余期数
 * 2、提前还款后的月利息是 剩余本金 / 月利率
 */
public class 等额本金计算器 {

    private Integer year = 2023;
    private Integer month = 2;

    @Test
    public void test(){
        getMonthlySupply(2170000,360,0.0465);
    }

    /**
     * 查看贷款月供详情
     */
    @Test
    public void getDetails(){
        Double totalRepayment = 0d;
        Double totalInterest = 0d;
        Double totalPrincipal = 0d;
        for (int i = 1; i <= 360; i++) {
            System.out.print("第 " + i + " 期 " + getDate());
            LoadData loadData = getMonthlySupplyDetails(360, 2170000, 0.0465, i);
            totalRepayment = getResult(loadData.getTotal(),totalRepayment);
            totalInterest = getResult(loadData.getInterest(),totalInterest);
            totalPrincipal = getResult(loadData.getPrincipal(),totalPrincipal);
        }

//        for (int i = 1; i <= 360; i++) {
//            LoadData loadData = getMonthlySupplyDetails(360, 600000, 0.031, i);
//            totalRepayment = getResult(loadData.getTotal(),totalRepayment);
//            totalInterest = getResult(loadData.getInterest(),totalInterest);
//            totalPrincipal = getResult(loadData.getPrincipal(),totalPrincipal);
//        }

        System.out.println("总利息 ： "+totalInterest);
        System.out.println("总本金 ： "+totalPrincipal);
        System.out.println("总额 ： "+totalRepayment);
    }

    /**
     * 通用月供计算
     * @param loadAmount 剩余本金总额
     * @param loanMonths 提前还后的还要还几次月供
     * @param yearRate 贷款月利率
     */
    public void getMonthlySupply(double loadAmount, int loanMonths, double yearRate){
//        double loadAmount = 1957805.56;   //
//        int loanMonths = 120;             //
//        double yearRate = 0.0465;         //
        double monthRate = yearRate/12;   //
        //每月应还本金：贷款金额÷分期数
        double principalEveryMonth = getResult(loadAmount / loanMonths,0);
        for (int monthNum = 1; monthNum <= loanMonths; monthNum++) {
            // 剩余贷款本金
            double remainPrincipal = loadAmount - principalEveryMonth*(monthNum - 1);
            //每月应还利息：剩余贷款本金*月利率
            double interestMonth = getResult(remainPrincipal*monthRate,0);
            System.out.print("应还本金："+principalEveryMonth);
            System.out.print("应还利息："+interestMonth);
            double total = getResult(principalEveryMonth,interestMonth);
            System.out.println("应还总额："+total);
        }
    }

    /**
     * 查看提前还款利息总额
     */
    @Test
    public void getTotalInterest(){
        int yearNum = 30;
        for (int i = 0; i < yearNum; i++) {
            System.out.print((i+1) + " 年后一次性还完 ");
            double v1 = getLoadData(360, 600000, 0.031, i+1);
            double v2 = getLoadData(360, 2170000, 0.0465, i+1);
            System.out.print(" 公积金利息 "+ v1);
            System.out.print(" 商贷利息 " + v2);
            System.out.println(" 利息总额 " + getResult(v1,v2));
        }
    }


    /**
     * 等额本金
     *
     * 等额本金计算公式：每月还款金额 = （贷款本金 / 还款月数） + （本金 — 已归还本金累计额） × 每月利率
     *
     * 等额本金还款计算公式:
     *
     * 1.每月月供额=(贷款本金÷还款月数)+(贷款本金-已归还本金累计额)×月利率
     * 2.每月应还本金=贷款本金÷还款月数
     * 3.每月应还利息=剩余本金×月利率=(贷款本金-已归还本金累计额)×月利率
     * 4.每月月供递减额=每月应还本金×月利率=贷款本金÷还款月数×月利率
     * 5.总利息=〔(总贷款额÷还款月数+总贷款额×月利率)+总贷款额÷还款月数×(1+月利率)〕÷2×还款月数-总贷款额
     */

    /**
     * 计算等额本金月供
     * @param loanMonths 贷款月数  int loanMonths, double loadAmount, double yearRate, int yearNum
     * @param loadAmount 贷款总额
     * @param yearRate 贷款利率
     * @param yearNum 年数
     * @return
     */
    public double getLoadData(int loanMonths, double loadAmount, double yearRate, int yearNum){
        double monthRate = yearRate/12; //贷款月利率
        double principalEveryMonth = getResult(loadAmount / loanMonths,0);//每月应还本金：贷款金额÷分期数
        double totalInterest = 0;
        //各期利息
        for (int i = 1; i < (yearNum * 12 + 1); i++) {
            //每月应还利息：剩余贷款本金*月利率
            totalInterest += getResult((loadAmount - principalEveryMonth*(i - 1))*monthRate,0);
        }
        return getResult(totalInterest,0);
    }


    /**
     * 计算等额本金月供
     * @param loanMonths 贷款月数  int loanMonths, double loadAmount, double yearRate, int yearNum
     * @param loadAmount 贷款总额
     * @param yearRate 贷款利率
     * @param monthNum 月数
     * @return
     */
    public LoadData getMonthlySupplyDetails(int loanMonths, double loadAmount, double yearRate, int monthNum){
        double monthRate = yearRate/12; //贷款月利率
        //每月应还本金：贷款金额÷分期数
        double principalEveryMonth = getResult(loadAmount / loanMonths,0);
        //每月应还利息：剩余贷款本金*月利率
        double interestMonth = getResult((loadAmount - principalEveryMonth*(monthNum - 1))*monthRate,0);
        System.out.print("应还本金："+principalEveryMonth);
        System.out.print("应还利息："+interestMonth);
        double total = getResult(principalEveryMonth,interestMonth);
        System.out.println("应还总额："+total);
        return new LoadData(principalEveryMonth,interestMonth,total);
    }

    public Double getResult(double v1, double v2){
        double totalV = v1 + v2;
        DecimalFormat format = new DecimalFormat("#.00");
        return Double.parseDouble(format.format(totalV));
    }

    public String getDate(){
        month ++;
        if (month > 12){
            month = 1;
            year ++;
        }
        return year + "年" + month + "月";
    }
}
